
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace Swaf.Call
{
	/// <summary>
	/// Exposes the ability to get the SOAP request and response
	/// </summary>
	public class SoapHttpClientProtocolEx : SoapHttpClientProtocol
	{
		private byte[] m_SoapRequestMsg = null;
		private byte[] m_SoapResponseMsg = null;
		
		/// <summary>
		/// Default constructor
		/// </summary>
		public SoapHttpClientProtocolEx() {}

		/// <summary>
		/// Property to get or set the SOAP request
		/// </summary>
		public byte[] SoapRequest
		{
			get {return m_SoapRequestMsg;}
			set {m_SoapRequestMsg = value;}
		}
		
		/// <summary>
		/// Property to get or set the SOAP response
		/// </summary>
		public byte[] SoapResponse
		{
			get {return m_SoapResponseMsg;}
			set {m_SoapResponseMsg = value;}
		}
	}

	/// <summary>
	/// Expose the SOAP message on the client
	/// </summary>
	public class SoapMessageAccessClientExtension : SoapExtension
	{ 
		Stream oldStream = null;
		Stream newStream = null;
		
		/// <summary>
		/// Initialize data 
		/// </summary>
		public override Object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) 
		{
			return null;
		}

		/// <summary>
		/// Initialize data 
		/// </summary>
		public override Object GetInitializer(Type t) 
		{
			return typeof(SoapMessageAccessClientExtension);
		}
    
		/// <summary>
		/// Initialize
		/// </summary>
		public override void Initialize(object initializer) {}
	    
		/// <summary>
		/// Process the SOAP message
		/// </summary>
		public override void ProcessMessage(SoapMessage message)
		{
			switch (message.Stage) 
			{
				case SoapMessageStage.BeforeSerialize:
					break;

				case SoapMessageStage.AfterSerialize:
					StoreRequestMessage(message);
					// Pass it off as the actual stream
					Copy(newStream, oldStream);
					// Indicate for the return that we don't wish to chain anything in
					break;

				case SoapMessageStage.BeforeDeserialize:
					StoreResponseMessage(message);
					// Pass it off as the actual stream
					break;

				case SoapMessageStage.AfterDeserialize:
					break;

				default:
					throw new ArgumentException("Invalid Soap Message stage [" + message.Stage + "]", "message");
			}
		}
	    
		/// <summary>
		/// Chain the memory streams
		/// </summary>
		public override Stream ChainStream(Stream stream) 
		{
			// Store old
			oldStream = stream;
			newStream = new MemoryStream();

			// Return new stream
			return newStream;
		}

		/// <summary>
		/// Store message in our slot in the SoapHttpClientProtocol-derived class
		/// </summary>
		private void StoreRequestMessage(SoapMessage message) 
		{
			// Rewind the source stream
			newStream.Position = 0;

			// Store message in our slot in the SoapHttpClientProtocol-derived class
			byte[] bufEncSoap = new Byte[newStream.Length];
			newStream.Read(bufEncSoap, 0, bufEncSoap.Length);
			((SoapHttpClientProtocolEx)(((SoapClientMessage)message).Client)).SoapRequest = bufEncSoap;
		}

		/// <summary>
		/// Store message in our slot in the SoapHttpClientProtocol-derived class
		/// </summary>
		private void StoreResponseMessage(SoapMessage message) 
		{
			Stream tempStream = new MemoryStream();
			Copy(oldStream, tempStream);

			// Store message in our slot in the SoapHttpClientProtocol-derived class
			byte[] bufEncSoap = new Byte[tempStream.Length];
			tempStream.Read(bufEncSoap, 0, bufEncSoap.Length);
			((SoapHttpClientProtocolEx)(((SoapClientMessage)message).Client)).SoapResponse = bufEncSoap;

			Copy(tempStream, newStream);
		}

		/// <summary>
		/// Copy the streams
		/// </summary>
		void Copy(Stream from, Stream to) 
		{
			if (from.CanSeek == true)
				from.Position = 0;
			TextReader reader = new StreamReader(from);
			TextWriter writer = new StreamWriter(to);
			writer.WriteLine(reader.ReadToEnd());
			writer.Flush();
			if (to.CanSeek == true)
				to.Position = 0;
		}
	}
	/// <summary>
	///  Specifies a SOAP extension should run with an XML Web service method
	/// </summary>
	[AttributeUsage(AttributeTargets.Method)]
	public class SoapMessageAccessClientExtensionAttribute : SoapExtensionAttribute 
	{
		private Int32 priority;
		
		/// <summary>
		/// Get the extension type
		/// </summary> 
		public override Type ExtensionType 
		{
			get { return typeof(SoapMessageAccessClientExtension); }
		}
		
		/// <summary>
		/// Property to get or set the SOAP message priority
		/// </summary>
		public override Int32 Priority 
		{
			get {return priority;}
			set {priority = value;}
		}
	}
}